home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / midi / gfft.lha / gfft-2.03 / source / gfft-2.03-source.lha / ok.c < prev    next >
C/C++ Source or Header  |  1996-01-02  |  10KB  |  415 lines

  1. /***************************************************************************
  2.  *          Copyright (C) 1994  Charles P. Peterson                  *
  3.  *         4007 Enchanted Sun, San Antonio, Texas 78244-1254             *
  4.  *              Email: Charles_P_Peterson@fcircus.sat.tx.us                *
  5.  *                                                                         *
  6.  *          This is free software with NO WARRANTY.                  *
  7.  *          See gfft.c, or run program itself, for details.              *
  8.  *              Support is available for a fee.                      *
  9.  ***************************************************************************
  10.  *
  11.  * Program:     gfft--General FFT analysis
  12.  * File:        ok.c
  13.  * Purpose:     OK! Do it!  (Whatever it is to be done)
  14.  * Author:      Charles Peterson (CPP)
  15.  * History:     23-August-1993 CPP; Created.
  16.  *              5-Aug-94 CPP (1.05); Fix nameless append mode
  17.  *              1-Oct-94 CPP (1.14); Fix 'not enough frames' off-by-1 error
  18.  *              10-Feb-95 CPP (1.38); Cleanup if output stopped
  19.  *              13-Feb-95 CPP (1.40); Header on spectrum files
  20.  * Comment:
  21.  */
  22.  
  23. #include <string.h>
  24. #include "gfft.h"
  25. #include "settings.h" /* Power, Amplitude, ReadPtr */
  26. #include "format.h"   /* ID_8SVX */
  27.  
  28.  
  29. static void check_output_parameters (BOOLEAN do_it_for_real);
  30. static void check_plot_parameters (void);
  31. static void spectrum_file_cleanup (void );
  32.  
  33.  
  34. static BOOLEAN temporary_name_used = FALSE;
  35.  
  36. /*
  37.  * First, the interface(s)
  38.  */
  39.  
  40. char *ok (char *arguments)
  41. {
  42.     if (InputFormat.zero != 0)
  43.     {
  44.     int sample_width = (InputFormat.bits > 8) ? 16 : 8;
  45.     InputFormat.zero = ((unsigned long) 0xffffffff >> 
  46.                 (33 - sample_width)) + (unsigned long) 1;
  47.     }
  48.     CATCH_ERROR
  49.     {
  50.     do_ok (TRUE);
  51.     }
  52.     ON_ERROR
  53.     {
  54.     spectrum_file_cleanup ();
  55.     }
  56.     END_CATCH_ERROR;
  57.  
  58.     return arguments;
  59. }
  60.  
  61. char *re_plot (char *arguments)
  62. {
  63.     check_plot_parameters ();
  64.     if (WriteName && strlen(WriteName))
  65.     {
  66.     OkWriteName = WriteName;  /* Probably used Append to load pre-ex */
  67.     }
  68.     if (!OkWriteName || !strlen(OkWriteName))
  69.     {
  70.     error_message (NO_WRITE_FILE);
  71.     RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  72.     }
  73.     do_re_plot ();
  74.     return arguments;
  75. }
  76.  
  77. char *re_output (char *arguments)
  78. {
  79.     CATCH_ERROR
  80.     {
  81.     check_output_parameters (TRUE);
  82.     do_re_output ();
  83.     if (WritePtr != stdout) 
  84.     {
  85.         FILE *write_ptr = WritePtr;
  86.         WritePtr = NULL;
  87.         fclose (write_ptr);
  88.     }
  89.     if (Plot)
  90.     {
  91.         ok_plot ();
  92.     }
  93.     if (temporary_name_used) WriteName = NULL;
  94.     }
  95.     ON_ERROR
  96.     {
  97.     spectrum_file_cleanup ();
  98.     }
  99.     END_CATCH_ERROR;
  100.     return arguments;
  101. }
  102.  
  103. static void spectrum_file_cleanup (void)
  104. {
  105.     if (WritePtr != stdout && WritePtr != NULL) 
  106.     {
  107.     FILE *write_ptr = WritePtr;
  108.     WritePtr = NULL;
  109.     fclose (write_ptr);
  110.     }
  111.     if (temporary_name_used) WriteName = NULL;
  112. }    
  113.  
  114. /*
  115.  * Now, the 'main routine' used by OK
  116.  */
  117.  
  118. ULONG do_ok (BOOLEAN do_it_for_real)
  119. {
  120.     ULONG bins_used = 0;
  121.  
  122.     if (!ReadPtr)
  123.     {
  124.     error_message (NO_READ_FILE);
  125.     RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  126.     }
  127.     if (NumberBins == INVALID_BINS)
  128.     {
  129.     error_message (INVALID_BINS_SPEC);
  130.     RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  131.     }
  132.     if (Interleave == INVALID_INTERLEAVE)
  133.     {
  134.     error_message (INVALID_INTERLEAVE_SPEC);
  135.     RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  136.     }
  137.     check_output_parameters (do_it_for_real);
  138.  
  139.     if (FileFormat)
  140.     {
  141.     if (!FileFormatOK)
  142.     {
  143.         error_message (FORMAT_NOT_OK);
  144.         RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  145.     }
  146.     if ((OneShotOnly || RepeatOnly) && FileFormat != ID_8SVX)
  147.     {
  148.         error_message (ONESHOT_BUT_NOT_8SVX);
  149.         RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  150.     }
  151.     OkRate = (Rate == AUTO_RATE) ? FileRate : Rate;/* user may ovride */
  152.     OkOffset = FileDataOffset;
  153.     OkChannels = FileChannels;
  154.  
  155.     OkOctaveOffset = ok_octave_offset (TRUE);
  156.  
  157.     if (OkOctaveOffset == 0)
  158.     {
  159.         ULONG available_frames = FileFrames;
  160.  
  161.         OkStartFrame = StartFrame;
  162.         OkStartFrame += (RepeatOnly) ? FileOneShotHiFrames : 0;
  163.         available_frames -= (RepeatOnly) ? FileOneShotHiFrames : 0;
  164.         available_frames -= (OneShotOnly) ? FileRepeatHiFrames : 0;
  165.         OkFrames = available_frames - StartFrame;
  166.         if (OkFrames < 1)
  167.         {
  168.         error_message (NOT_ENOUGH_FRAMES);
  169.         RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  170.         }
  171.     }
  172.     else
  173.     {
  174.     /*
  175.      * Deal with multi-octave stuff (and, OneShot/Repeat stuff here too)
  176.      * since user asked for higher octave
  177.      * We use indirection inherent in OkFrames and OkStartFrame.
  178.      * (Otherwise, format reader defaults FileFrames to first octave.)
  179.      *
  180.      * NOTE!  Currently multi-octaves are only supported for 8SVX.
  181.      * Also, I ought to move this stuff back into the format module for
  182.      * better modularity.  Someday.
  183.      */
  184.         ULONG octave_and_oneshot_offset = 0;
  185.         int power2 = 1;
  186.         int i;
  187.  
  188.         for (i = 0; i < OkOctaveOffset; i++)
  189.         {
  190.         octave_and_oneshot_offset += power2 * FileFrames;
  191.         power2 *= 2;
  192.         }
  193.         OkFrames = power2 * FileFrames;
  194.         if (RepeatOnly)
  195.         {
  196.         OkFrames -= power2 * FileOneShotHiFrames;
  197.         octave_and_oneshot_offset += power2 * FileOneShotHiFrames;
  198.         }
  199.         if (OneShotOnly)
  200.         {
  201.         OkFrames -= power2 * FileRepeatHiFrames;
  202.         }
  203.         OkStartFrame = StartFrame + octave_and_oneshot_offset;
  204.         OkFrames -= StartFrame;
  205.         if (OkFrames < 1)
  206.         {
  207.         error_message (NOT_ENOUGH_FRAMES);
  208.         RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  209.         }
  210.     }
  211.     /*
  212.      * Now, see if we have enough frames for user's specification
  213.      */
  214.     if (Frames <= OkFrames)
  215.     {
  216.         OkFrames = Frames;
  217.     }
  218.     else
  219.     {
  220.         if (Frames != ULONG_MAX)
  221.         {
  222.         error_message (NOT_ENOUGH_FRAMES);
  223.         RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  224.         }
  225.     }
  226.     }
  227.     else /* Unformatted file */
  228.     {
  229.     if (Rate == AUTO_RATE)
  230.     {
  231.         error_message (NO_RATE_SPECIFIED);
  232.         RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  233.     }
  234.     OkRate = Rate;
  235.     OkOffset = StartByte;
  236.     if (FileFrames == 0)  /* If file length unknown */
  237.     {
  238.         OkFrames = ULONG_MAX;
  239.         OkStartFrame = StartFrame;
  240.     }
  241.     else
  242.     {
  243.         if (FileFrames <= StartFrame) /* StartFrame is 0 based */
  244.         {
  245.         error_message (NOT_ENOUGH_FRAMES);
  246.         RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  247.         }
  248.         OkFrames = FileFrames - StartFrame;
  249.         OkStartFrame = StartFrame;
  250.     }
  251.     OkChannels = 1;     /* unformatted files must have 1 channel now */
  252.     }
  253.     if (Channel > OkChannels || Channel < 1)
  254.     {
  255.     error_message (SPEC_CHANNEL_UNAVAIL);
  256.     RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  257.     }
  258.     /*
  259.      * To permit multiple analyses without redundantly entering filename
  260.      * it is reset to beginning here
  261.      */
  262.     ok_rewind ();
  263.  
  264.     if (Power || Amplitude)
  265.     {
  266.     if (Header && do_it_for_real)
  267.     {
  268.         fprintf (WritePtr, "#FFT\n");
  269.         write_settings (WritePtr, "#", TRUE, FALSE);
  270.     }
  271.     if (Time3D)
  272.     {
  273.         bins_used = ok_time3d_spectrum (do_it_for_real);
  274.     }
  275.     else
  276.     {
  277.         bins_used = ok_spectrum (do_it_for_real);
  278.     }
  279.     }
  280.     else
  281.     {
  282.     bins_used = ok_fft (do_it_for_real);
  283.     }
  284.     if (do_it_for_real)
  285.     {
  286.     if (WritePtr != stdout)
  287.     {
  288.         FILE *write_ptr = WritePtr;
  289.         WritePtr = NULL;
  290.         fclose (write_ptr);
  291.     }
  292.     if (Plot)
  293.     {
  294.         ok_plot ();
  295.     }
  296.     if (temporary_name_used) WriteName = NULL;
  297.     }
  298.     return bins_used;
  299. }
  300.  
  301.     
  302. /*
  303.  * Now, the checking and utilty routines
  304.  */
  305.  
  306. /*
  307.  *  User selects 1 for lowest octave, 2 for second, etc.
  308.  *   (Special case...0 for highest)
  309.  * however, 8SVX octaves are stored in order highest first
  310.  * so, we compute OkOctaveOffset to match storage order
  311.  */
  312.  
  313. int ok_octave_offset (BOOLEAN report_error)
  314. {
  315.     int octave_offset = 0;
  316.     if (Octave != 0)
  317.     {
  318.     octave_offset = FileOctaves - Octave;
  319.     if (octave_offset < 0)
  320.     {
  321.         if (report_error) error_message (OCTAVE_NOT_PRESENT);
  322.         RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  323.     }
  324.     }
  325.     return octave_offset;
  326. }
  327.  
  328.  
  329. static void check_output_parameters (BOOLEAN do_it_for_real)
  330. {
  331.  
  332.     temporary_name_used = FALSE;
  333.  
  334.     if (Rate == INVALID_RATE)   /* Last rate command was invalid */
  335.     {
  336.     error_message (NO_RATE_SPECIFIED);
  337.     RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  338.     }
  339.     if (SmoothingSegments == INVALID_SMOOTHING)
  340.     {
  341.     error_message (INVALID_SMOOTHING_SPEC);
  342.     RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  343.     }
  344.     check_plot_parameters ();
  345.     if (do_it_for_real)
  346.     {
  347.     if (WriteName && strlen (WriteName) && !WritePtr)
  348.     {
  349.         char temp_filename[MAX_PATH+1];
  350.  
  351.         strcpy (temp_filename, WriteName);
  352.         if (Appending)
  353.         {
  354.         set_append (temp_filename);
  355.         }
  356.         else
  357.         {
  358.         set_write (temp_filename);
  359.         }
  360.     }
  361.     if (Plot && !WritePtr)
  362.     {
  363.         extern int Old_File_Count;
  364.         int file_number = (CombinePlots) ? Old_File_Count+1 : 1;
  365.         char *read_name = (ReadName) ? ReadName : NullString;
  366.         char temp_filename[MAX_PATH+1];
  367.         char temp_name[MAX_PATH+1];
  368.  
  369.         temporary_name_used = TRUE;
  370.  
  371.         stcgfn (temp_filename, read_name);  /* SAS/C SYSTEM DEPENDENT */
  372.         sprintf (temp_name, TEMP_DATAFILE_NAME, temp_filename,
  373.              file_number);
  374.         /*
  375.          * (1.05)
  376.          */
  377.         if (Appending)
  378.         {
  379.         set_append (temp_name);
  380.         }
  381.         else
  382.         {
  383.         set_write (temp_name);
  384.         }
  385.     }
  386.     if (!WritePtr)
  387.     {
  388.         error_message (NO_WRITE_FILE);
  389.         RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  390.     }
  391.     OkWriteName = WriteName;
  392.  
  393.     } /* end if (do_it_for_real) */
  394. }
  395.  
  396.  
  397. static void check_plot_parameters (void)
  398. {
  399.     if (WritePtr == stdout && Plot)
  400.     {
  401.     error_message (CANT_PLOT_FROM_STDOUT);
  402.     RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  403.     }
  404.     if (RotX == INVALID_ROTATION)
  405.     {
  406.     error_message (INVALID_ROTATION_SPEC);
  407.     RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  408.     }
  409.     if (RotZ == INVALID_ROTATION)
  410.     {
  411.     error_message (INVALID_ROTATION_SPEC);
  412.     RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
  413.     }
  414. }
  415.